package io.kiki.stack.netty.command;

import io.kiki.stack.netty.config.Configs;
import io.kiki.stack.netty.exception.DeserializationException;
import io.kiki.stack.netty.exception.SerializationException;
import io.kiki.stack.netty.invoker.RequestContext;
import io.kiki.stack.netty.protocol.CommonCommandCode;
import io.kiki.stack.netty.serialization.CustomSerializer;
import io.kiki.stack.netty.serialization.CustomSerializerManager;
import io.kiki.stack.netty.serialization.SerializerManager;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;

@Slf4j
@Setter
@Getter
public class AbstractResponseCommand extends ResponseCommand {
    private static final long serialVersionUID = 1L;
    private Object responseObject;

    private String responseClass;

    private CustomSerializer customSerializer;
    private Object responseHeader;

    private String errorMsg;

    public AbstractResponseCommand() {
        super(CommonCommandCode.response);
    }

    public AbstractResponseCommand(Object response) {
        super(CommonCommandCode.response);
        this.responseObject = response;
    }

    public AbstractResponseCommand(int id, Object response) {
        super(CommonCommandCode.response, id);
        this.responseObject = response;
    }


    @Override
    public void serializeClazz() throws SerializationException {
        if (this.getResponseClass() != null) {
            try {
                byte[] clz = this.getResponseClass().getBytes(Configs.DEFAULT_CHARSET);
                this.setClazz(clz);
            } catch (UnsupportedEncodingException e) {
                throw new SerializationException("Unsupported charset: " + Configs.DEFAULT_CHARSET, e);
            }
        }
    }

    @Override
    public void deserializeClazz() throws DeserializationException {
        if (this.getClazz() != null && this.getResponseClass() == null) {
            try {
                this.setResponseClass(new String(this.getClazz(), Configs.DEFAULT_CHARSET));
            } catch (UnsupportedEncodingException e) {
                throw new DeserializationException("Unsupported charset: " + Configs.DEFAULT_CHARSET, e);
            }
        }
    }

    @Override
    public void serializeContent(RequestContext requestContext) throws SerializationException {
        if (this.getResponseObject() != null) {
            try {
                if (this.getCustomSerializer() != null && this.getCustomSerializer().serializeContent(this)) {
                    return;
                }

                this.setContent(SerializerManager.serializer.serialize(this.responseObject));
            } catch (SerializationException e) {
                throw e;
            } catch (Exception e) {
                throw new SerializationException("Exception caught when serialize content of rpc response command!", e);
            }
        }
    }

    @Override
    public void deserializeContent(RequestContext requestContext) throws DeserializationException {
        if (this.getResponseObject() == null) {
            try {
                if (this.getCustomSerializer() != null && this.getCustomSerializer().deserializeContent(this, requestContext)) {
                    return;
                }
                if (this.getContent() != null) {
                    this.setResponseObject(SerializerManager.serializer.deserialize(this.getContent(), this.responseClass));
                }
            } catch (DeserializationException e) {
                throw e;
            } catch (Exception e) {
                throw new DeserializationException("Exception caught when deserialize content of rpc response command!", e);
            }
        }

    }

    @Override
    public void serializeHeader(RequestContext requestContext) throws SerializationException {
        if (this.getCustomSerializer() != null) {
            try {
                this.getCustomSerializer().serializeHeader(this);
            } catch (SerializationException e) {
                throw e;
            } catch (Exception e) {
                throw new SerializationException("Exception caught when serialize header of rpc response command!", e);
            }
        }
    }

    @Override
    public void deserializeHeader(RequestContext requestContext) throws DeserializationException {
        if (this.getHeader() != null && this.getResponseHeader() == null) {
            if (this.getCustomSerializer() != null) {
                try {
                    this.getCustomSerializer().deserializeHeader(this, requestContext);
                } catch (DeserializationException e) {
                    throw e;
                } catch (Exception e) {
                    throw new DeserializationException("Exception caught when deserialize header of rpc response command!", e);
                }
            }
        }
    }


    public CustomSerializer getCustomSerializer() {
        if (this.customSerializer != null) {
            return customSerializer;
        }
        if (this.responseClass != null) {
            this.customSerializer = CustomSerializerManager.getCustomSerializer(this.responseClass);
        }
        if (this.customSerializer == null) {
            this.customSerializer = CustomSerializerManager.getCustomSerializer(this.getCommandCode());
        }
        return this.customSerializer;
    }


}
